#!/usr/bin/env python
# -*- coding:utf8 -*-
"""
Author : mafei
@Date   : 2019/12/02

"""
import time
import logging

from rest_framework.views import APIView

from mmonitor.utils.connectors import get_redis_conn

from ..custom_request import extend_request, NotJsonFormatBody, InvalidParameter
from mmonitor.models.cache import CacheInteractor

extend_request()

logger = logging.getLogger(u'mmonitor-api')

from django.http import JsonResponse

'''
正确  20
参数类错误(参数缺失, 参数类型不符预期等)  30
业务条件不满足类错误  40
未知错误(被全局处理)  90
'''


class ResponseMixin(object):
    def _response(self, code, msg, data=None):
        ret = {
            'code': code,
            'msg': msg,
            'status': 'success' if code == 20 else 'error'
        }
        if data is not None:
            ret['data'] = data
        return JsonResponse(ret)

    def ok_response(self, data=None, msg=u'操作成功'):
        return self._response(20, msg=msg, data=data)

    def invalid_param_response(self, msg, data=None):
        return self._response(30, msg=msg, data=data)

    def logic_error_response(self, msg, data=None):
        return self._response(40, msg=msg, data=data)

    def error_response(self, msg, data=None):
        return self._response(50, msg=msg, data=data)


def verify_input(query_dict, position, required_keys):
    for key in required_keys:
        if key not in query_dict:
            raise InvalidParameter(u'{} 缺少参数 {}'.format(position, key))


class ViewFileBase(ResponseMixin, APIView):
    logger = logger


class ViewBase(ResponseMixin, APIView):
    logger = logger

    def __init__(self, **initkwargs):
        # self.create_list = {}  没有使用, 应该是当初拷贝代码简单拷贝过来了
        # self.single_ins = False  # only allow one connect at running time 没有使用
        # self.create_event_data = []
        super(ViewBase, self).__init__(**initkwargs)
        self.query_dict = {}
        self._cache = None
        self._session = None

    @property
    def cache(self):
        if not self._cache:
            self._cache = CacheInteractor()
        return self._cache

    def prepare_data(self, request):
        is_attack, msg = self.check_attack(request.method.lower(), request.client_ip)
        if is_attack:
            return False, self.invalid_param_response(msg=msg)
        self.query_dict = request.query_dict
        # if 'key' not in request.query_data or request.query_data['key'].strip() != API_ACCESS_KEY:
        #     return False, self.invalid_param_response(msg='auth failure')
        verify_input(request.query_data, 'query', getattr(self, 'required_query_keys', []))
        verify_input(request.request_data, 'body', getattr(self, 'required_body_keys', []))
        return True, ''

    def check_attack(self, method, client_ip):
        is_attack, msg = False, ""
        return is_attack, msg

    def http_method_not_allowed(self, request, *args, **kwargs):
        # 将默认的 405 转换成 200
        return self.invalid_param_response(u'Method not allowed.')

    def dispatch(self, request, *args, **kwargs):
        # Try to dispatch to the right method; if a method doesn't exist,
        # defer to the error handler. Also defer to the error handler if the
        # request method isn't on the approved list.
        try:
            if request.method.lower() in self.http_method_names:
                status, msg = self.prepare_data(request)  # 初始检查
                if not status:
                    return msg
                handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
            else:
                handler = self.http_method_not_allowed
            return handler(request, *args, **kwargs)
        except Exception as e:
            # 全局错误处理
            import traceback
            traceback.print_exc()
            if isinstance(e, NotJsonFormatBody):
                return self.invalid_param_response(msg=u'only JSON format data allowed')

            if isinstance(e, InvalidParameter):
                return self.invalid_param_response(msg=e.message)

            # 未知的错误
            self.logger.exception(u'Error happened when processing request: ')
            msg = u'系统当前繁忙, 请稍后再试'

            if request.debug_enabled:
                import traceback
                return self.error_response(msg=msg,
                                           data=traceback.format_exception_only(e.__class__, e))
            else:
                return self.error_response(msg)

    def check_login(self, func):
        def wrapper(request, *args, **kwargs):
            print(request.session.keys)
            print(request.session.get("user"))
            if 'user' not in request.session:
                d = {"code": 40, "msg": "还没登录", 'status': 'error'}
                return JsonResponse(d)
            else:
                return func(request, *args, **kwargs)

        return wrapper


class ViewSecurityBase(ViewBase):

    def __init__(self):
        super(ViewSecurityBase, self).__init__()

    logger = logger

    def check_attack(self, method, client_ip):
        is_attack, msg = False, ""
        if method == 'get':
            return is_attack, msg
        namespace = "{}_{}".format(client_ip, time.strftime("%M", time.localtime()))
        if self.cache.get(client_ip, namespace=namespace) > 2:
            return True, "操作太频繁了,请稍后再试"
        self.cache.incr(client_ip, namespace=namespace, life_cycle=30)
        return is_attack, msg